package com.party.admin.biz.crowdfund;

import com.alibaba.druid.support.json.JSONUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.party.admin.biz.activity.ActivityBizService;
import com.party.admin.biz.refund.RefundBizService;
import com.party.admin.biz.system.MemberBizService;
import com.party.admin.biz.webSocket.WebSocketBizService;
import com.party.admin.jms.publisher.service.ISupportRefundPubulisherService;
import com.party.admin.redisPubSub.publish.RedisMsgPublish;
import com.party.admin.redisPubSub.subscribe.SubScribeMessage;
import com.party.admin.utils.RealmUtils;
import com.party.admin.web.dto.output.crowdfund.ProjectForActivityOutput;
import com.party.admin.web.dto.output.crowdfund.SupportCountOutput;
import com.party.common.constant.Constant;
import com.party.common.paging.Page;
import com.party.common.utils.DateUtils;
import com.party.core.exception.BusinessException;
import com.party.core.model.activity.Activity;
import com.party.core.model.crowdfund.*;
import com.party.core.model.distributor.DistributorRelation;
import com.party.core.model.member.Member;
import com.party.core.model.member.PartnerMember;
import com.party.core.model.order.OrderForm;
import com.party.core.model.order.OrderType;
import com.party.core.model.wechat.WechatMerchants;
import com.party.core.service.activity.IActivityService;
import com.party.core.service.crowdfund.*;
import com.party.core.service.crowdfund.biz.ProjectDetailCountBizService;
import com.party.core.service.distributor.IDistributorRelationService;
import com.party.core.service.member.IMemberService;
import com.party.core.service.member.IPartnerMemberService;
import com.party.core.service.member.biz.MemberPersonalCountBizService;
import com.party.core.service.order.IOrderFormService;
import com.party.core.service.order.IOrderRefundService;
import com.party.core.service.wechat.IWechatMerchantsService;
import com.party.pay.model.refund.WechatPayRefundResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 众筹支持业务接口
 * Created by wei.li
 *
 * @date 2017/3/30 0030
 * @time 16:44
 */


@SuppressWarnings("all")
@Service
public class SupportBizService {

    @Autowired
    private ISupportService supportService;

    @Autowired
    private RefundBizService refundBizService;

    @Autowired
    private ISupportRefundService supportRefundService;

    @Autowired
    private IProjectService projectService;

    @Autowired
    private IProjectRefundService projectRefundService;

    @Autowired
    private IOrderRefundService orderRefundService;

    @Autowired
    private ISupportRefundPubulisherService supportRefundPubulisherService;

    @Autowired
    private IOrderFormService orderFormService;

    @Autowired
    private WebSocketBizService webSocketBizService;

    @Autowired
    private IProjectReviseService projectReviseService;

    @Autowired
    private RedisMsgPublish redisMsgPublish;

    @Autowired
    private ProjectDetailCountBizService projectDetailCountBizService;

    @Autowired
    private IPartnerMemberService partnerMemberService;

    @Autowired
    private MemberPersonalCountBizService memberPersonalCountBizService;

    @Autowired
    private ITargetProjectService targetProjectService;

    @Autowired
    private IActivityService activityService;

    @Autowired
    private ActivityBizService activityBizService;

    @Autowired
    private ProjectBizService projectBizService;

    @Autowired
    private IMemberService memberService;

    @Autowired
    private ISupportTransferService supportTransferService;

    @Autowired
    private IWechatMerchantsService wechatMerchantsService;

    @Autowired
    private IDistributorRelationService distributorRelationService;

    @Autowired
    private ICrowdfundEventService crowdfundEventService;

    @Autowired
    private MemberBizService memberBizService;

    protected static Logger logger = LoggerFactory.getLogger(ProjectBizService.class);

    /**
     * 根据分销编号查询
     *
     * @param relationId 分销编号
     * @param page       分页参数
     * @return 支持列表
     */
    public List<SupportWithMember> listForDistributorId(String relationId, String merchantId, Page page) {
        String memberId = RealmUtils.getCurrentUser().getId();
        SupportWithMember supportWithMember = new SupportWithMember();
        supportWithMember.setRelationId(relationId);
        supportWithMember.setMerchantId(merchantId);
        List<SupportWithMember> supportWithMemberList = supportService.distributorList(supportWithMember, page);
        for (SupportWithMember swm : supportWithMemberList) {
            //替换手机号
            String phone = memberBizService.replacePhone(memberId, swm.getFavorerMobile());
            swm.setFavorerMobile(phone);
        }
        return supportWithMemberList;
    }

    /**
     * 众筹项目查询支持
     *
     * @param projectId 项目比昂
     * @param page      分页参数
     * @return 支持列表
     */
    public List<SupportWithMember> listForProjectId(String projectId, String startTime, String merchantId, Page page) {
        String memberId = RealmUtils.getCurrentUser().getId();

        SupportWithMember supportWithMember = new SupportWithMember();
        supportWithMember.setProjectId(projectId);
        supportWithMember.setExcludePayStatus(Constant.SUPPORT_PAY_STATUS_UNPAID);
        supportWithMember.setStartTime(startTime);
        supportWithMember.setMerchantId(merchantId);
        List<SupportWithMember> supportWithMemberList = supportService.listWithMemberAndMerchant(supportWithMember, page);

        for (SupportWithMember swm : supportWithMemberList) {
            //替换手机号
            String phone = memberBizService.replacePhone(memberId, swm.getFavorerMobile());
            swm.setFavorerMobile(phone);
        }
        return supportWithMemberList;
    }



    /**
     * 众筹项目查询支持(可通过支付状态搜索)
     *
     * @param projectId 项目ID
     * @param page      分页参数
     * @return 支持列表
     */
    public List<SupportWithMember> listForProjectId(String projectId, String startTime, String merchantId, Integer payStatus, Page page) {
        SupportWithMember supportWithMember = new SupportWithMember();
        supportWithMember.setProjectId(projectId);
        supportWithMember.setPayStatus(payStatus);
        supportWithMember.setExcludePayStatus(Constant.SUPPORT_PAY_STATUS_UNPAID);
        supportWithMember.setStartTime(startTime);
        supportWithMember.setMerchantId(merchantId);
        List<SupportWithMember> supportWithMemberList = supportService.listWithMemberAndMerchant(supportWithMember, page);
        return supportWithMemberList;
    }


    /**
     * 支持退款信息
     *
     * @param id 支持编号
     */
    public void refund(String id, String memberId, String sessionId) {
        refund(id);
        try {
            //众筹是否全部退完
            Support support = supportService.get(id);
            Project project = projectService.get(support.getProjectId());
            boolean refundAll = supportService.isPayStatusChangeAll(project.getId());
            if (refundAll) {
                // 是否全部退款成功
                Integer refundFailCount = supportService.refundAllFailCount(project.getId());
                String message = "";
                // 没有退款失败的, 则全部退款成功
                if (Integer.valueOf(0).equals(refundFailCount)) {
                    message = "退款已全部完成!";
                } else {
                    message = "抱歉有" + refundFailCount + "人退款失败, 请切换到退款失败标签页查看详情. 如有问题, 可点击<校正>按钮";
                }
                Map<String, String> json = Maps.newHashMap();
                json.put("memberId", memberId);
                json.put("sessionId", sessionId);
                json.put("message", message);
                String param = JSONUtils.toJSONString(json);
                redisMsgPublish.publish(SubScribeMessage.CHANNEL_NAME, param);
                try {
                    projectReviseService.reviseFavorer(project.getId());
                } catch (Exception e) {
                    logger.error("众筹退款后矫正众筹支持失败", e);
                }
            }
        } catch (Exception e) {
            logger.error("众筹退款后webSocket推送消息失败", e);
        }
    }

    /**
     * 支持退款信息
     *
     * @param id 支持编号
     */
    public void refund(String id) {
        Support support = supportService.get(id);
        Project project = projectService.get(support.getProjectId());

        //验证是否已经退款
        OrderForm orderForm = orderFormService.get(support.getOrderId());
        if (null != orderForm && orderForm.getStatus().equals(Constant.SUPPORT_PAY_STATUS_REFUND)) {
            return;
        }

        WechatPayRefundResponse response = null;
        try {
            response = (WechatPayRefundResponse) refundBizService.refund(support.getOrderId(), null);
        } catch (BusinessException be) {
            WechatPayRefundResponse rp = new WechatPayRefundResponse();
            rp.setErrCodeDes(be.getMessage());
            orderRefundService.orderTrade(support.getOrderId(), rp);
        } catch (Exception e) {
            //退款失败
            projectService.crowdfundRefundFaile(project);//将zc_project状态置为退款失败的状态
            support.setPayStatus(Constant.SUPPORT_PAY_STATUS_FAIL);
            supportService.update(support);
            logger.info("众筹支持订单退款异常", e);
        }

        if (null == response) {
            //退款失败
            projectService.crowdfundRefundFaile(project);
            support.setPayStatus(Constant.SUPPORT_PAY_STATUS_FAIL);
            supportService.update(support);
            return;
        }

        //退款成功
        if (Constant.WECHAT_SUCCESS.equals(response.getReturnCode()) && Constant.WECHAT_SUCCESS.equals(response.getResultCode())) {
            supportRefundService.refund(support, response);

            //众筹是否全部退完
            project = projectService.get(support.getProjectId());

            boolean refundAll = supportService.isRefundAll(project.getId());

            if (refundAll) {
                projectRefundService.refund(project);
            } else {
                projectRefundService.refundNoSuccess(project);
            }
        }

        //退款失败
        else {

            //如果订单已经退款
            if (Constant.REFUND_ALL_DES.equals(response.getErrCodeDes())) {
                supportRefundService.refund(support, response);

                //众筹是否全部退完
                project = projectService.get(support.getProjectId());
                boolean refundAll = supportService.isRefundAll(project.getId());
                if (refundAll) {
                    projectRefundService.refund(project);
                } else {
                    projectRefundService.refundNoSuccess(project);
                }
            } else {

                //退款失败
                projectService.crowdfundRefundFaile(project);//将zc_project状态置为退款失败的状态
                support.setPayStatus(Constant.SUPPORT_PAY_STATUS_FAIL);
                supportService.update(support);
                orderRefundService.orderTrade(support.getOrderId(), response);
            }
        }

        // 退款后, 众筹的统计分析修改
        try {
            projectDetailCountBizService.countProjectSomeDay(support.getProjectId(), support.getCreateDate());
        } catch (Exception e) {
            logger.error("退款后, 众筹的统计分析修改异常", e);
        }

        try {
            TargetProject targetProject = targetProjectService.findByProjectId(support.getProjectId());
            Activity activity = activityService.get(targetProject.getTargetId());
            PartnerMember partnerMember = partnerMemberService.findByPartnerAndMember(activity.getMember(), support.getFavorerId());
            memberPersonalCountBizService.countOne(partnerMember);
        } catch (Exception e) {
            logger.error("退款时实时更新众筹数量异常 ", e);
        }
    }


    /**
     * 退款队列
     *
     * @param id 支持编号
     */
    public void sendRefund(String id) {
        Support support = supportService.get(id);
        if (null == support) {
            throw new BusinessException("支持信息不存在");
        }
        support.setPayStatus(Constant.SUPPORT_PAY_STATUS_REFUNDING);
        supportService.update(support);
        supportRefundPubulisherService.send(id);
    }

    /**
     * 退款队列
     *
     * @param id 支持编号
     */
    public void sendRefundWithMemberId(String id, String memberId, String sessionId) {
        supportRefundPubulisherService.send(id, memberId, sessionId);
    }

    /**
     * 图表数据
     *
     * @param projectId 项目编号
     * @return 输出视图
     */
    public SupportCountOutput chart(String projectId) {

        Project project = projectService.get(projectId);
        Date now = new Date();
        Date startDate = DateUtils.addDay(now, -30);
        List<Date> dateList = DateUtils.getDateDifference(project.getCreateDate(), now);
        if (dateList.size() > 30) {
            dateList = DateUtils.getDateDifference(startDate, now);
        }
        List<SupportCount> supportCountList
                = supportService.count(DateUtils.formatDateTime(startDate), DateUtils.formatDate(now), projectId);
        return conformity(dateList, supportCountList);
    }


    /**
     * 整合数据
     *
     * @param dateList         时间列表
     * @param supportCountList 统计列表
     * @return 输出视图
     */
    public SupportCountOutput conformity(List<Date> dateList, List<SupportCount> supportCountList) {
        SupportCountOutput supportCountOutput = new SupportCountOutput();
        List<String> dates = Lists.newArrayList();
        List<Float> paymentList = Lists.newArrayList();
        List<Integer> favorerList = Lists.newArrayList();

        for (Date date : dateList) {
            Float payment = 0f;
            Integer favorer = 0;
            for (SupportCount supportCount : supportCountList) {
                if (DateUtils.formatDate(date, "yyyy-MM-dd")
                        .equals(DateUtils.formatDate(supportCount.getDate(), "yyyy-MM-dd"))) {
                    payment = supportCount.getPayment();
                    favorer = supportCount.getFavorerNum();
                    break;
                }
            }
            paymentList.add(payment);
            favorerList.add(favorer);
            dates.add(DateUtils.formatDate(date, "yyyy-MM-dd"));
        }

        supportCountOutput.setDateList(dates);
        supportCountOutput.setFavorerList(favorerList);
        supportCountOutput.setPaymentList(paymentList);
        return supportCountOutput;
    }

    /**
     * @param id                活动id
     * @param supportWithMember
     * @param page
     * @param source
     * @return
     * @Author yifeng
     * @Description 众筹项目查询支持
     * @Date 9:18 2019/3/27
     **/
    public Map<String, Object> listForProjectCommonActivity(String id, SupportWithMember supportWithMember, Page page, Integer source) {
        Map<String, Object> map = Maps.newHashMap();
        page.setLimit(20);
        Activity activity = activityService.get(id);
        String memberId = RealmUtils.getCurrentUser().getId();
        //众筹金额
        float actualAmount = activityBizService.actualAmountForTargetId(id);
        List<SupportWithMember> supportWithMemberList = supportService.listWithMemberAndMerchant(supportWithMember, page);
        for (SupportWithMember swm:supportWithMemberList) {
            //替换手机号
            String phone = memberBizService.replacePhone(memberId,swm.getFavorerMobile());
            swm.setFavorerMobile(phone);
        }


        ProjectWithAuthor projectWithAuthor = new ProjectWithAuthor();
        projectWithAuthor.setTargetId(id);
        projectWithAuthor.setPayType(0);
        List<ProjectForActivityOutput> projectForActivityOutputList = projectBizService.projectForActivityList(projectWithAuthor, null, activity.getMember());

        projectWithAuthor.setPayType(1);
        List<ProjectForActivityOutput> dpProjectForActivityOutputList = projectBizService.projectForActivityList(projectWithAuthor, null, activity.getMember());
        projectWithAuthor.setPayType(null);

        Project project = projectService.get(supportWithMember.getProjectId());
        Member author = memberService.get(project.getAuthorId());


        // 获取转入的人
        Integer transferNum = supportTransferService.getShiftToPeopleTotal(activity.getId());

        map.put("transferNum", transferNum == null ? 0 : transferNum);

        map.put("actualAmount", actualAmount);
        map.put("activity", activity);
        map.put("projectId", supportWithMember.getProjectId());
        map.put("page", page);
        map.put("id", id);
        map.put("list", supportWithMemberList);
        map.put("name", author.getRealname());
        map.put("crowdfundNum", projectForActivityOutputList.size());
        map.put("directPayNum", dpProjectForActivityOutputList.size());

        map.put("merchantId", supportWithMember.getMerchantId());
        List<WechatMerchants> wechatMerchants = wechatMerchantsService.getMerchant(activity.getMember());
        map.put("wechatMerchants", wechatMerchants);
        map.put("source", source);
        return map;
    }

    /**
     * @param id         活动id
     * @param relationId 分销关系id
     * @param merchantId 商户id
     * @param page       分页参数
     * @return
     * @Author yifeng
     * @Description 根据分销关系编号查询支持列表
     * @Date 9:20 2019/3/27
     **/
    public Map<String, Object> listForDistributorCommonActivity(String id, String relationId, String merchantId, Page page) {
        Map<String, Object> map = Maps.newHashMap();
        page.setLimit(20);
        Activity activity = activityService.get(id);

        //众筹金额
        float actualAmount = activityBizService.actualAmountForTargetId(id);

        List<SupportWithMember> supportWithMemberList = listForDistributorId(relationId, merchantId, page);

        Integer directPayNum = projectService.directPaySizeForTargetId(id, null, 1);

        DistributorRelation distributorRelation = distributorRelationService.get(relationId);
        Member member = memberService.get(distributorRelation.getDistributorId());


        //获取转入的人
        Integer transferNum = supportTransferService.getShiftToPeopleTotal(activity.getId());
        map.put("transferNum", transferNum);
        map.put("actualAmount", actualAmount);
        map.put("directPayNum", directPayNum);
        map.put("activity", activity);
        map.put("page", page);
        map.put("relationId", relationId);
        map.put("name", member.getRealname());
        map.put("list", supportWithMemberList);
        map.put("merchantId", merchantId);
        List<WechatMerchants> wechatMerchants = wechatMerchantsService.getMerchant(activity.getMember());
        map.put("wechatMerchants", wechatMerchants);
        return map;
    }

    /**
     * @param eventId    主题id
     * @param relationId 分销关系id
     * @param merchantId 商户id
     * @param page       分页参数
     * @return
     * @Author yifeng
     * @Description 根据分销关系编号查询支持列表
     * @Date 9:22 2019/3/27
     **/
    public Map<String, Object> listForDistributorCommonEvent(String eventId, String relationId, String merchantId, Page page) {
        Map<String, Object> map = Maps.newHashMap();
        page.setLimit(20);
        DistributorRelation distributorRelation = distributorRelationService.get(relationId);
        Member author = memberService.get(distributorRelation.getDistributorId());

        Integer representNum = distributorRelationService.countForEvent(eventId);
        Integer projectNum = projectService.countForEvent(eventId);
        Integer directPayNum = projectService.dpCountForEvent(eventId, null);


        List<SupportWithMember> supportWithMemberList = listForDistributorId(relationId, merchantId, page);
        map.put("page", page);
        map.put("eventId", eventId);
        map.put("representNum", representNum);
        map.put("projectNum", projectNum);
        map.put("directPayNum", directPayNum);
        map.put("relationId", relationId);
        map.put("name", author.getRealname());
        map.put("list", supportWithMemberList);
        CrowdfundEvent crowdfundEvent = crowdfundEventService.get(eventId);
        map.put("crowdfundEvent", crowdfundEvent);
        map.put("merchantId", merchantId);
        List<WechatMerchants> wechatMerchants = wechatMerchantsService.getMerchant(crowdfundEvent.getCreateBy());
        map.put("wechatMerchants", wechatMerchants);
        return map;
    }

    /**
     * @param eventId    主题id
     * @param projectId  众筹id
     * @param merchantId 商户id
     * @param page       分页参数
     * @return
     * @Author yifeng
     * @Description 众筹项目查询支持
     * @Date 9:25 2019/3/27
     **/
    public Map<String, Object> listForRepresentCommonEvent(String eventId, Page page, SupportWithMember supportWithMember) {
        Map<String, Object> map = Maps.newHashMap();
        page.setLimit(20);
        Project project = projectService.get(supportWithMember.getProjectId());
        Member author = memberService.get(project.getAuthorId());
        List<SupportWithMember> supportWithMemberList = listForProjectId(supportWithMember.getProjectId(),
                null, supportWithMember.getMerchantId(), page);
        Integer representNum = distributorRelationService.countForEvent(eventId);
        Integer projectNum = projectService.countForEvent(eventId);

        map.put("representNum", representNum);
        map.put("projectNum", projectNum);
        map.put("eventId", eventId);
        map.put("page", page);
        map.put("list", supportWithMemberList);
        map.put("name", author.getRealname());
        CrowdfundEvent crowdfundEvent = crowdfundEventService.get(eventId);
        map.put("crowdfundEvent", crowdfundEvent);
        List<WechatMerchants> wechatMerchants = wechatMerchantsService.getMerchant(crowdfundEvent.getCreateBy());
        map.put("wechatMerchants", wechatMerchants);
        map.put("supportWithMember", supportWithMember);
        return map;
    }

    /**
     * @param id                活动id
     * @param supportWithMember 查询参数
     * @param page              分页参数
     * @return
     * @Author yifeng
     * @Description 众筹项目查询支持
     * @Date 9:26 2019/3/27
     **/
    public Map<String, Object> listForRepresentCommonActivity(String id, Page page, SupportWithMember supportWithMember) {
        Map<String, Object> map = Maps.newHashMap();
        page.setLimit(20);
        Activity activity = activityService.get(id);

        //众筹金额
        float actualAmount = activityBizService.actualAmountForTargetId(id);

        List<SupportWithMember> supportWithMemberList = supportService.listWithMemberAndMerchant(supportWithMember, page);

        Project project = projectService.get(supportWithMember.getProjectId());
        Member member = memberService.get(project.getAuthorId());

        ProjectWithAuthor projectWithAuthor = new ProjectWithAuthor();
        projectWithAuthor.setTargetId(id);
        projectWithAuthor.setPayType(1);//直接众筹
        List<ProjectForActivityOutput> dpProjectForActivityOutputList = projectBizService.projectForActivityList(projectWithAuthor, null, activity.getMember());
        projectWithAuthor.setPayType(0);
        List<ProjectForActivityOutput> projectForActivityOutputList = projectBizService.projectForActivityList(projectWithAuthor, null, activity.getMember());

        //获取转入的人
        Integer transferNum = supportTransferService.getShiftToPeopleTotal(activity.getId());

        map.put("transferNum", transferNum);
        map.put("actualAmount", actualAmount);
        map.put("crowdfundNum", projectForActivityOutputList.size());//众筹人数
        map.put("directPayNum", dpProjectForActivityOutputList.size());//直接付款人数
        map.put("activity", activity);
        map.put("projectId", supportWithMember.getProjectId());
        map.put("page", page);
        map.put("list", supportWithMemberList);
        map.put("name", member.getRealname());
        map.put("merchantId", supportWithMember.getMerchantId());
        List<WechatMerchants> wechatMerchants = wechatMerchantsService.getMerchant(activity.getMember());
        map.put("wechatMerchants", wechatMerchants);
        return map;
    }

    /**
     * @param eventId    主题id
     * @param projectId  众筹id
     * @param merchantId 商户id
     * @param page       分页
     * @return
     * @Author yifeng
     * @Description 主题的众筹的支持者列表
     * @Date 17:22 2019/3/25
     **/
    public Map<String, Object> listForProjectCommonEvent(Page page, String eventId, SupportWithMember supportWithMember, String startTime) {
        Map<String, Object> map = Maps.newHashMap();
        page.setLimit(20);
        List<SupportWithMember> supportWithMemberList = listForProjectId(supportWithMember.getProjectId(), startTime, supportWithMember.getMerchantId(), page);

        Integer representNum = distributorRelationService.countForEvent(eventId);
        Integer projectNum = projectService.countForEvent(eventId);
        Integer dpProjectNum = projectService.dpCountForEvent(eventId, null);

        Project project = projectService.get(supportWithMember.getProjectId());
        Member author = memberService.get(project.getAuthorId());

        map.put("representNum", representNum);
        map.put("projectNum", projectNum);
        map.put("dpProjectNum", dpProjectNum);
        map.put("eventId", eventId);
        map.put("page", page);
        map.put("list", supportWithMemberList);
        map.put("name", author.getRealname());
        map.put("startTime", startTime);
        CrowdfundEvent crowdfundEvent = crowdfundEventService.get(eventId);
        map.put("crowdfundEvent", crowdfundEvent);
        List<WechatMerchants> wechatMerchants = wechatMerchantsService.getMerchant(crowdfundEvent.getCreateBy());
        map.put("wechatMerchants", wechatMerchants);
        map.put("supportWithMember", supportWithMember);
        return map;
    }
}
